`timescale 1ns/1ns
`define k 256
`define m 16 //m=4,8,16,30
`define w 16 //w=k/m=64,32,16,8
`define p_256r1 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff
`define p_sm2 256'hFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF

module Mul_ecc (
			 input clk,//连到外部
			 input rst_n,//连到外部
			 input enable,//连到外部
			 input curve_sel, // curve_sel = 0 256r1 
							  //             1 sm2
			 input [`k-1:0] a,//连到外部
			 input [`k-1:0] b,//连到外部
			 //input [`k-1:0] p,//连到外部
			 input [`k+`m+2:0] S,//从内部REG取数
			 input [`k+`m+2:0] C,//从内部REG取数
			 output [`k+`m+2:0] carry,//连到内部REG上  
			 output [`k+`m+2:0] sum,//连到内部REG上
			 output	[`k-1:0] r,//连到外部
			 output reg end_flag,//连到外部
			 output reg busy
		   );

//wire [`k-1:0] p;

wire [`k+`m-1:0] b_sem;//左移m位的b

wire [`k+`m+15:0] b_sem2;//填充16bit0的bi

reg [4:0] i;

wire [`m+2:0] T;

wire c;
wire [31:0] C_sem;//C'

wire [31:0] x;//用sign将T补成32bit
wire sign;//T的符号位

wire [`k-1:0] R0,R1;

wire [`k+`m-1:0] PP;

wire [`k+`m-33:0] S_tree;
wire [`k+`m-1:0] C_tree;
wire [`k+`m-1:0] R0_tree;
wire [`k+`m-1:0] R1_tree;

wire [`k:0] rrr;//未模p的结果
/////////////////////////////////////////state machine//////////////////////////////////////////

//reg [1:0] state,next_state;

reg state,next_state;

parameter IDLE = 1'b0,
		  LOOP = 1'b1;
		  
always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		state <= IDLE;
	end
	else
	begin
		state <= next_state;
	end
end

always @(*)
begin
	case(state)
	IDLE:begin
			if(enable)
			begin
				next_state = LOOP;
			end
			else
			begin
				next_state = IDLE;
			end
		end
	LOOP:begin
			if(i == 5'd0)
			begin
				next_state = IDLE;
			end
			else
			begin
				next_state = LOOP;
			end
		end
	default:begin
				next_state = IDLE;
	end
	endcase
end

////////////////////////////////////////////////////////////////////////////////////////////////
//assign p = (curve_sel == 1'b0) ? `p_256r1 : `p_sm2;

assign b_sem = b << (`m);

assign b_sem2 = {16'd0,b_sem};

always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
	i <= 5'd17;
else if(next_state == LOOP)
	i <= i - 1;
else
	i <= 5'd17;
end

assign T = S[`k+`m+2:`k] + C[`k+`m+1:`k-1];//截掉超过第274bit的数
  
assign sign = T[`m+2];

assign x = {{13{sign}},T[`m+2:0]};

assign {c,C_sem} = {1'b0,S[`k-1:`k-32]} + {1'b0,C[`k-2:`k-33]};

assign R0 = (curve_sel == 1'b0) ?  ({x,(~x),32'b0,32'b0,(~x),32'b0,32'b0,x}) : ({x,32'b0,32'b0,32'b0,x,(~x),32'b0,x});

//assign R1 = (c==1'b0) ? {{32{~sign}},{31'b0,sign},{32{~sign}},{32{~sign}},{31'b0,(~sign)},{32{sign}},{32{sign}},32'b0} : {{32{~sign}},{32{1'b1}},{32{1'b1}},{32{1'b1}},{32{sign}},{32{sign}},{32{sign}},32'd1};

assign R1 = (curve_sel == 1'b0) ? ((c == 1'b0) ? {{32{~sign}},{31'b0,sign},{32{~sign}},{32{~sign}},{31'b0,(~sign)},{32{sign}},{32{sign}},32'b0} : {{32{~sign}},{32{1'b1}},{32{1'b1}},{32{1'b1}},{32{sign}},{32{sign}},{32{sign}},32'd1}) : ((c==1'b0) ? {{32{1'b1}},{32{1'b1}},{32{1'b1}},{32{1'b1}},{32{~sign}},{31'b0,(~sign)},{32{sign}},32'b0} : {{31'b0,(~sign)},{32{sign}},{32{sign}},{32{sign}},{32{1'b0}},{32{sign}},{32{sign}},{31'b0,{1'b1}}});

assign S_tree = S[`k-33:0] << `m; 

assign C_tree = {C_sem,{C[`k-34:0],1'b0}} << `m;

assign R0_tree = R0 << `m;

assign R1_tree = R1 << `m;

assign rrr = sum[`k+`m+2:`m]+carry[`k+`m+1:`m-1];

//assign r = (rrr > {1'b0,p}) ? (rrr - p) : rrr;

assign r = (curve_sel == 1'b0) ? ((rrr > {1'b0,`p_256r1}) ? (rrr - `p_256r1) : rrr) : ((rrr > {1'b0,`p_sm2}) ? (rrr - `p_sm2) : rrr);

//wire[2:0] cs = {3{1'b0}};  //补齐C_tree
//wire[34:0] ss = {{3{sign}},{32{1'b0}}};//补齐S_tree
wire[2:0] r1s = (curve_sel == 1'b0) ? {3{~sign}} : ((c==1'b0) ? {3{1'b1}} : {3{1'b0}});//补齐R1_tree
//wire[2:0] r0s = {3{1'b0}};//补齐R0_tree

assign PP = a * b_sem2[((i+1)*`m-1)-:16];

//booth bt (.a(a),.b(b_sem2[((i+1)*`m-1)-:16]),.o(PP));

CSA_Tree csatree (.a({{3{1'b0}},R0_tree}),.b({r1s,R1_tree}),.d({{3{1'b0}},C_tree}),.e({3'b00,PP}),.f({{{3{sign}},{32{1'b0}}},S_tree}),.c(carry),.s(sum));

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		end_flag <= 1'b0;
	end
	else if(i == 6'd1)
	begin
		end_flag <= 1'b1;
	end
	else
	begin
		end_flag <= 1'b0;
	end
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		busy <= 1'b0;
	end
	else if(enable)
	begin
		busy <= 1'b1;
	end
	else if(i == 6'd1)
	begin
		busy <= 1'b0;
	end
	else
	begin
		busy <= busy;
	end
end

endmodule